/**
 * Filename Row.java 2021年03月06日
 * Copyright © Ehome Co.Ltd. All Rgiths Reserved.
 *
 * @author wuyingchao
 */
package com.ehome.poct.core.dao.entity.check;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.ehome.exception.BizException;
import com.ehome.poct.core.api.dto.TestDataDTO;
import com.ehome.poct.core.api.dto.check.gold.TestConfPoctStripMappingDTO;
import com.ehome.poct.core.api.dto.check.gold.TestConfPoctStripTypeDTO;
import com.ehome.poct.core.api.dto.common.CommonUtil;
import com.ehome.poct.core.api.vo.StripKpisVO;
import com.ehome.poct.core.constant.BizCode;
import com.ehome.poct.core.dao.mapping.CheckReportMapping;
import com.ehome.poct.core.pasre.report.symbol.SymbolStrategy;
import com.ehome.poct.core.pasre.report.symbol.SymbolStrategyFactory;
import com.ehome.poct.core.pasre.report.symbol.dto.ReportSymbolDTO;
import com.ehome.poct.core.pasre.report.text.TextStrategy;
import com.ehome.poct.core.pasre.report.text.TextStrategyFactory;
import com.ehome.poct.core.pasre.report.text.dto.ReportTextDTO;
import lombok.Data;
import org.assertj.core.error.ShouldHaveAtLeastOneElementOfType;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.*;

/**
 * 行数据
 *
 * @author wyc
 * @date 2021/03/06 17:02
 **/
@Data
@Slf4j
public class Row {
    private CheckReportMapping reportMapping;
    private List<Object> columns;
    private Integer order;
    private String[] analysisResults;

    public Row(Integer order, String[] analysisResults) {
        this.reportMapping = SpringUtil.getBean(CheckReportMapping.class);
        this.columns = new ArrayList<>();
        this.order = order;
        this.analysisResults = analysisResults;
    }

    /**
     * 给行数据的列赋值
     *
     * @param data
     * @param dataType
     * @param stripType
     * @param k
     * @return
     */
    public List<Object> paresToColumns(TestDataDTO data, Integer dataType, TestConfPoctStripTypeDTO stripType, Map.Entry<String, List<TestConfPoctAnalysisDO>> k, Integer isChild) {
        // 过滤出对应的检测分析
        BigDecimal value = getValueByOrder(data, order);

        Optional<TestConfPoctAnalysisDO> optional = k.getValue().stream()
                .filter(poctConfDo -> value.compareTo(poctConfDo.getLogicMinValue()) >= 0 && value.compareTo(poctConfDo.getLogicMaxValue()) < 0)
                .findFirst();

        if (optional.isEmpty()) {
            log.error("找不到对应金标仪配置项 testDataId:[{}] , stripTypeCode:[{}] , stripBatch:[{}] , value:[{}]"
                    , data.getTestDataDetailId(), data.getStripTypeCode(), data.getStripBatch(), value);
            throw new BizException(BizCode.REPORT_CONFIG_INFO_MISSING);
        }

        TestConfPoctAnalysisDO analysis = optional.get();
        // 检测值html标签
        //String valueHtml = CommonUtil.translateTestData(data, value,isChild);

        String valueHtml = getReportSymbolAndText(data, value, isChild);

        if (dataType == 2) {
            // 代码
            if (data.isMultiValue()) {
                columns.add(k.getKey());
            } else {
                columns.add(data.getStripMapping().getStripMapName());
            }
            // 检测项目中文全称
            columns.add(stripType.getFullName());
            // 替换换行标签
            valueHtml = valueHtml.replaceAll("<br/>", "\n");
        } else {
            // 检测项目简称
            columns.add(k.getKey());
            // 添加Html样式
            valueHtml = CommonUtil.createHtmlTag(analysis.getColor(), valueHtml);
        }
        switch (stripType.getType()) {
            // 定量
            case 1:
                setRowValue1(stripType, valueHtml);
                break;
            // 定性
            case 2:
                setRowValue2(analysis.getColor(), reportMapping.toKpis(k.getValue()), valueHtml, dataType);
                break;
            // 半定量
            case 3:
                setRowValue3(stripType, valueHtml, analysis);
                break;
            default:
                return null;
        }
        return columns;
    }

    /**
     * 给行数据的列赋值 crp 单独处理
     *
     * @param dataType
     * @param stripType
     * @return
     */
    public List<Object> paresToColumnsCRP(String stripName, Integer dataType, TestConfPoctStripTypeDTO stripType,String superOrNomal,String shortName) {
        // 检测项目简称
        columns.add(shortName+ (2==dataType?"":"检测"));
        if (dataType == 2) {
            columns.add(stripName + "\n" + shortName );
        }
        setRowValue1(stripType, superOrNomal.replaceAll("常规:","").replace("常规:",""));
        return columns;
    }


    /**
     * 获取报告符号及文本信息
     *
     * @param testDataDTO
     * @param value
     * @param isChild
     */
    private static String getReportSymbolAndText(TestDataDTO testDataDTO, BigDecimal value, Integer isChild) {
        String symbol = getSymbol(testDataDTO.getStripType(), value, isChild);

        TextStrategy textStrategy = TextStrategyFactory.getINSTANCE().get(testDataDTO.getStripTypeCode());
        TestConfPoctStripMappingDTO stripMappingDTO = testDataDTO.getStripMapping();
        ReportTextDTO reportTextDTO = ReportTextDTO.builder()
                .checkResult(value).symbol(symbol).minValue(stripMappingDTO.getMin()).maxValue(stripMappingDTO.getMax()).build();
        return textStrategy.getReportText(reportTextDTO);
    }

    /**
     * 获取报告符号
     *
     * @param strip
     * @param value
     * @param isChild
     * @return
     */
    private static String getSymbol(TestConfPoctStripTypeDTO strip, BigDecimal value, Integer isChild){
        if (Objects.isNull(strip)) {
            return "";
        }
        if (!ArrayUtil.contains(CommonUtil.DL_STRIP_TYPE, strip.getTypeCode())) {
            return "";
        }
        SymbolStrategy symbolStrategy = SymbolStrategyFactory.getINSTANCE().get(strip.getTypeCode());
        ReportSymbolDTO reportSymbolDTO = ReportSymbolDTO.builder().checkResult(value).confPoctStripType(strip).child(0 == isChild).build();
        return symbolStrategy.getSymbol(reportSymbolDTO);
    }

    /**
     * 定量
     *
     * @param stripType
     * @param valueHtml
     */
    private void setRowValue1(TestConfPoctStripTypeDTO stripType, String valueHtml) {
        // 检测结果
        columns.add(valueHtml);
        // 幼儿参考范围
        if (StrUtil.isNotEmpty(stripType.getChildReference())) {
            columns.add(stripType.getChildReference());
        }
        // 成人参考范围
        if (StrUtil.isNotEmpty(stripType.getStandardReference())) {
            columns.add(stripType.getStandardReference());
        }
        // 参考范围
        if (StrUtil.isNotEmpty(stripType.getReference())) {
            columns.add(stripType.getReference());
        }
        // 单位
        columns.add(stripType.getUnit());
    }

    /**
     * 定性
     *
     * @param color
     * @param kpis
     * @param valueHtml
     * @param dataType
     */
    private void setRowValue2(String color, List<StripKpisVO> kpis, String valueHtml, Integer dataType) {
        // 定性结果
        String analysisResult = analysisResults[order.intValue() - 1];
        if (dataType == 2) {
            // 检测值
            columns.add(valueHtml);
            // 定性结果
            columns.add(analysisResult);
        } else {
            // 第一列赋空值
            columns.add(0,"");
            // 检测值
            columns.add("单位值：" + valueHtml);
            // 定性结果
            columns.add("结果：" + CommonUtil.createHtmlTag(color, analysisResult));
        }
        // 参考指标
        columns.add(kpis);
    }

    /**
     * 半定量
     *
     * @param stripType
     * @param valueHtml
     * @param analysis
     */
    private void setRowValue3(TestConfPoctStripTypeDTO stripType, String valueHtml, TestConfPoctAnalysisDO analysis) {
        // 检测结果
        columns.add(valueHtml);
        // 结果区间
        columns.add(analysis.getResult());
        // 参考值
        columns.add(stripType.getReference());
        // 单位
        columns.add(stripType.getUnit());
    }

    private BigDecimal getValueByOrder(TestDataDTO data, Integer valueOrder) {
        switch (valueOrder) {
            case 2 :
                return data.getValue2();
            case 3 :
                return data.getValue3();
            case 4 :
                return data.getValue4();
            case 1 :
            default:
                return data.getValue1();
        }
    }
}